//
//  UnitCubeShape.cpp
//  Ray Tracer
//
//  Created by Kaila, Ashish on 4/8/13.
//  Copyright (c) 2013 Kaila, Ashish. All rights reserved.
//

#include "UnitCubeShape.h"

UnitCubeShape::UnitCubeShape(Material* material)
: SceneObject(NULL)
{
    UnitSquare* bottomSquare = new UnitSquare(material);
    bottomSquare->rotate('x', 90);
    bottomSquare->translate(Vector3D(0, 0, 0.5));
    
    UnitSquare* topSquare = new UnitSquare(material);
    topSquare->rotate('x', -90);
    topSquare->translate(Vector3D(0, 0, 0.5));
    
    UnitSquare* leftSquare = new UnitSquare(material);
    leftSquare->rotate('y', 90);
    leftSquare->translate(Vector3D(0, 0, -0.5));
    
    UnitSquare* rightSquare = new UnitSquare(material);
    rightSquare->rotate('y', -90);
    rightSquare->translate(Vector3D(0, 0, -0.5));
    
    UnitSquare* frontSquare = new UnitSquare(material);
    frontSquare->translate(Vector3D(0, 0, 0.5));
    
    UnitSquare* backSquare = new UnitSquare(material);
    backSquare->rotate('y', 180);
    backSquare->translate(Vector3D(0, 0, 0.5));
    
    _cube.addChildShape(bottomSquare);
    _cube.addChildShape(topSquare);
    _cube.addChildShape(leftSquare);
    _cube.addChildShape(rightSquare);
    _cube.addChildShape(frontSquare);
    _cube.addChildShape(backSquare);
}

bool UnitCubeShape::intersect(Ray3D& ray,
                              const Matrix4x4& worldToModel,
                              const Matrix4x4& modelToWorld) const
{
    Matrix4x4 childModelToWorld = modelToWorld * getTransform();
    Matrix4x4 childWorldToModel = getInvTransform() * worldToModel;
    
    return _cube.intersect(ray, childWorldToModel, childModelToWorld);    
}

// Returns true if world point is contained within the object
bool UnitCubeShape::contains(const Point3D& worldPoint, const Matrix4x4& worldToModel) const
{
    Point3D point = worldToModel * worldPoint;
    return ((point[0] >= -0.5) && (point[0] <= 0.5)) &&
           ((point[1] >= -0.5) && (point[1] <= 0.5)) &&
           ((point[2] >= -0.5) && (point[2] <= 0.5));
}